package com.tiger.service.schedule;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.tiger.utils.DateTimeUtils;
import com.tiger.utils.RedisUtils;
import com.tiger.utils.Sync2ElasticsearchUtils;
import com.tiger.mapper.adminPage.*;
import com.tiger.mapper.base.EntryMapper;
import com.tiger.mapper.base.ExcelMapper;
import com.tiger.mapper.base.UserArticleMapper;
import com.tiger.mapper.common.AutoCreateUserArticleMapper;
import com.tiger.pojo.adminPage.*;
import com.tiger.pojo.base.Entry;
import com.tiger.pojo.base.Excel;
import com.tiger.pojo.base.UserArticle;
import com.tiger.pojo.common.AutoCreateUserArticle;
import com.tiger.pojo.excel.*;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.*;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.List;

/**
 * 用于定时从数据库中获取新的文章信息，更新到 elasticsearch 中
 * @author HuXuehao (StudiousTiger)
 * @desc 这个类的作用是
 * @date 2022/3/11
 */
@Slf4j
@Component
public class ScheduledService {
    @Autowired
    private AutoCreateUserArticleMapper autoCreateUserArticleMapper;
    @Autowired
    private UserArticleMapper userArticleMapper;
    @Autowired
    private UserIncreaseInfoMapper userIncreaseInfoMapper;
    @Autowired
    private UserActiveInfoMapper userActiveInfoMapper;
    @Autowired
    private UserWorksIncreaseInfoMapper userWorksIncreaseInfoMapper;
    @Autowired
    private UserGenderInfoMapper userGenderInfoMapper;
    @Autowired
    private UserCodeAgeInfoMapper userCodeAgeInfoMapper;
    @Autowired
    private ReportTypeInfoMapper reportTypeInfoMapper;
    @Autowired
    private ExcelMapper excelMapper;
    @Autowired
    private EntryMapper entryMapper;
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private RedisUtils redisUtil;
    @Autowired
    private Sync2ElasticsearchUtils sync2ElasticsearchUtils;

    @Value("${minio.bucketNameOfXls}")
    private String bucketNameOfXls;
    @Value("${minio.endPoint}")
    private String endPoint;

    /**
     * 每天的0点执行一次 （将今天新增的文章存到elasticsearch中）
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void updateArticle() {
        sync2ElasticsearchUtils.timingSync();
    }

    /**
     * 每隔15天的凌晨3点执行一次,将符合条件的内容加到 UserArticle
     */
    @Scheduled(cron = "0 0 3 15 * ?")
    public void autoCreateUserArticle(){
        try {
            List<AutoCreateUserArticle> autoCreateUserArticles = autoCreateUserArticleMapper.selectList(null);
            if (autoCreateUserArticles.size() > 0){
                for (AutoCreateUserArticle autoCreateUserArticle : autoCreateUserArticles) {
                    UserArticle userArticle = new UserArticle();
                    userArticle.setUserId(autoCreateUserArticle.getUserId());
                    userArticle.setTitleAuthorId(autoCreateUserArticle.getTitleAuthorId());
                    userArticle.setUserReplyId(autoCreateUserArticle.getUserReplyId());
                    userArticle.setArticleTitleId(autoCreateUserArticle.getArticleTitleId());
                    userArticle.setArticleCreatDate(DateTimeUtils.currentDateTime2SQLTimestamp());
                    userArticleMapper.insert(userArticle);
                }
            }

            log.info("自动生成文章已执行，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        }
    }

    /**
     * 每周一的1点执行一次 （用户活跃度）
     */
    @Scheduled(cron = "0 0 1 ? * 2")
    public void createXlsOfUserActive(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            List<UserActiveInfo> userActiveInfos = userActiveInfoMapper.selectList(null);
            List<UserActiveData> list = new ArrayList<>();
            String date = DateTimeUtils.currentDateOfFormStr();

            // 1、将查询到的结果填入list
            for (UserActiveInfo userActiveInfo : userActiveInfos) {
                UserActiveData data = new UserActiveData();
                data.setDatetime(userActiveInfo.getDatetime());
                data.setActiveCount(userActiveInfo.getUserActiveCount());
                data.setExcelCreateTime(date);
                list.add(data);
            }
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,UserActiveData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【用户活跃趋势】周报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Excel excel = new Excel();
            excel.setExcelName(fileName);
            excel.setExcelDownloadUrl(fileName);
            excel.setExcelSize(fileSize);
            excel.setExcelClassify("userActive");
            excel.setExcelDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            excelMapper.insert(excel);

            log.info("用户活跃趋势，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每个月的一号的2点执行一次 （用户增长趋势）
     */
    @Scheduled(cron = "0 0 2 1 * ?")
    public void createXlsOfUserIncrease(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            List<UserIncreaseInfo> userIncreaseInfos = userIncreaseInfoMapper.selectList(null);
            List<UserIncreaseData> list = new ArrayList<>();
            String date = DateTimeUtils.currentDateOfFormStr();

            // 1、将查询到的结果填入list
            for (UserIncreaseInfo userIncreaseInfo : userIncreaseInfos) {
                UserIncreaseData data = new UserIncreaseData();
                data.setDatetime(userIncreaseInfo.getDatetime());
                data.setUserCount(userIncreaseInfo.getUserCount());
                data.setExcelCreateTime(date);
                list.add(data);
            }
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,UserIncreaseData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【用户增长趋势】月报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Excel excel = new Excel();
            excel.setExcelName(fileName);
            excel.setExcelDownloadUrl(fileName);
            excel.setExcelSize(fileSize);
            excel.setExcelClassify("userIncrease");
            excel.setExcelDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            excelMapper.insert(excel);

            log.info("用户增长趋势，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每个月的一号的3点执行一次 （作品增长趋势）
     */
    @Scheduled(cron = "0 0 3 1 * ?")
    public void createXlsOfWorksIncrease(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            List<UserWorksIncreaseInfo> userWorksIncreaseInfos = userWorksIncreaseInfoMapper.selectList(null);
            List<WorksIncreaseData> list = new ArrayList<>();
            String date = DateTimeUtils.currentDateOfFormStr();

            // 1、将查询到的结果填入list
            for (UserWorksIncreaseInfo userWorksIncreaseInfo : userWorksIncreaseInfos) {
                WorksIncreaseData data = new WorksIncreaseData();
                data.setDatetime(userWorksIncreaseInfo.getDatetime());
                data.setErrorCount(userWorksIncreaseInfo.getErrorCount());
                data.setQuestionCount(userWorksIncreaseInfo.getQuestionCount());
                data.setBlinkCount(userWorksIncreaseInfo.getBlinkCount());
                data.setExcelCreateTime(date);
                list.add(data);
            }
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,WorksIncreaseData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【作品增长趋势】月报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Excel excel = new Excel();
            excel.setExcelName(fileName);
            excel.setExcelDownloadUrl(fileName);
            excel.setExcelSize(fileSize);
            excel.setExcelClassify("worksIncrease");
            excel.setExcelDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            excelMapper.insert(excel);

            log.info("作品增长趋势，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每个月的一号的4点执行一次 （举报类型分布情况）
     */
    @Scheduled(cron = "0 0 4 1 * ?")
    public void createXlsOfReportedType(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            List<ReportTypeInfo> reportTypeInfos = reportTypeInfoMapper.selectList(null);
            List<ReportedTypeData> list = new ArrayList<>();
            String date = DateTimeUtils.currentDateOfFormStr();

            // 1、将查询到的结果填入list
            for (ReportTypeInfo reportTypeInfo : reportTypeInfos) {
                ReportedTypeData data = new ReportedTypeData();
                data.setReportedClassify(reportTypeInfo.getReportedClassify());
                data.setReportedCount(reportTypeInfo.getCount());
                data.setExcelCreateTime(date);
                list.add(data);
            }
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,ReportedTypeData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【举报类型分布】月报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Excel excel = new Excel();
            excel.setExcelName(fileName);
            excel.setExcelDownloadUrl(fileName);
            excel.setExcelSize(fileSize);
            excel.setExcelClassify("reportedType");
            excel.setExcelDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            excelMapper.insert(excel);

            log.info("举报类型分布，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每个月的一号的5点执行一次 （用户码龄分布情况）
     */
    @Scheduled(cron = "0 0 5 1 * ?")
    public void createXlsOfUserCodeAge(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            List<UserCodeAgeInfo> userCodeAgeInfos = userCodeAgeInfoMapper.selectList(null);
            List<UserCodeAgeData> list = new ArrayList<>();
            String date = DateTimeUtils.currentDateOfFormStr();

            // 1、将查询到的结果填入list
            for (UserCodeAgeInfo userCodeAgeInfo : userCodeAgeInfos) {
                UserCodeAgeData data = new UserCodeAgeData();
                data.setCodeAgeScope(userCodeAgeInfo.getCodeAgeScope());
                data.setCodeAgeCount(userCodeAgeInfo.getCodeAgeCount());
                data.setExcelCreateTime(date);
                list.add(data);
            }
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,UserCodeAgeData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【用户码龄占比】月报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Excel excel = new Excel();
            excel.setExcelName(fileName);
            excel.setExcelDownloadUrl(fileName);
            excel.setExcelSize(fileSize);
            excel.setExcelClassify("userCodeAge");
            excel.setExcelDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            excelMapper.insert(excel);

            log.info("用户码龄分布，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每个月的一号的5点执行一次 （用户性别分布情况）
     */
    @Scheduled(cron = "0 0 5 1 * ?")
    public void createXlsOfUserGender(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            List<UserGenderInfo> userCodeAgeInfos = userGenderInfoMapper.selectList(null);
            List<UserGenderData> list = new ArrayList<>();
            String date = DateTimeUtils.currentDateOfFormStr();

            // 1、将查询到的结果填入list
            for (UserGenderInfo userGenderInfo : userCodeAgeInfos) {
                UserGenderData data = new UserGenderData();
                data.setUserGender(userGenderInfo.getUserGender());
                data.setUserCount(userGenderInfo.getUserCount());
                data.setExcelCreateTime(date);
                list.add(data);
            }
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,UserGenderData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【用户性别占比】月报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Excel excel = new Excel();
            excel.setExcelName(fileName);
            excel.setExcelDownloadUrl(fileName);
            excel.setExcelSize(fileSize);
            excel.setExcelClassify("userGender");
            excel.setExcelDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            excelMapper.insert(excel);

            log.info("用户性别分布，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 每周一的2点执行一次 （百科词条信息）
     */
    @Scheduled(cron = "0 0 2 ? * 2")
    public void createXlsEntryOfBaike(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            Object[] baikeKey = redisUtil.hGetAllKey("baike_count");
            Object[] baikesCount = redisUtil.hGetAllValue("baike_count");
            if (baikeKey.length <= 0) {
                log.info("百科词条信息，已执行");
                return;
            }
            // 1、将查询到的结果填入list
            ArrayList<BaikeInfoData> list = new ArrayList<>();
            for (int i = 0; i < baikeKey.length; i++) {
                BaikeInfoData data = new BaikeInfoData(baikeKey[i]+"", baikesCount[i]+"");
                list.add(data);
            }
            String date = DateTimeUtils.currentDateOfFormStr();
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,BaikeInfoData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【百科词条】周报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Entry entry = new Entry();
            entry.setEntryValue(fileName);
            entry.setEntryDownloadUrl(fileName);
            entry.setEntrySize(fileSize);
            entry.setEntryType("baike");
            entry.setEntryDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            entryMapper.insert(entry);

            log.info("百科词条信息，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }

    /**
     * 每周一的3点执行一次 （翻译词条信息）
     */
    @Scheduled(cron = "0 0 3 ? * 2")
    public void createXlsEntryOfTranslate(){
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        OutputStream out = null;
        InputStream in = null;
        try {
            Object[] translateKey = redisUtil.hGetAllKey("translate_count");
            Object[] translateCount = redisUtil.hGetAllValue("translate_count");
            if (translateKey.length <= 0) {
                log.info("翻译词条信息，已执行");
                return;
            }
            // 1、将查询到的结果填入list
            ArrayList<TranslateInfoData> list = new ArrayList<>();
            for (int i = 0; i < translateKey.length; i++) {
                TranslateInfoData data = new TranslateInfoData(translateKey[i]+"", translateCount[i]+"");
                list.add(data);
            }
            String date = DateTimeUtils.currentDateOfFormStr();
            // 3、os:要写入的输出流； UserActiveData.class：注释类用于获取配置信息，例如列名的配置
            ExcelWriter excelWriter = EasyExcel.write(os,TranslateInfoData.class).build();
            // 4、设置sheet名
            WriteSheet writeSheet = EasyExcel.writerSheet("数据").build();
            // 5、list：要写入的内容
            excelWriter.write(list,writeSheet).finish();
            // 6、获取输出流
            out = excelWriter.writeContext().writeWorkbookHolder().getOutputStream();
            // 7、将输出流 强转成 输入流 （使用字节数组缓存数据），用于下面上传到 minio 使用
            // 7.1、(ByteArrayOutputStream)out : 将 输出流 强转成 字节数组输出流
            // 7.2、((ByteArrayOutputStream)out).toByteArray() : 字节数组输出流 转换成 字节数组
            // 7.3、new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：将字节数组 转换成 字节数组输入流
            // 7.4、InputStream in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray())：字节数组输入流 转换成 输入流
            in = new ByteArrayInputStream(((ByteArrayOutputStream)out).toByteArray());
            String fileSize = getSize(in.available());
            // 8、判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfXls).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfXls).build());
            }

            // 9、上传excel
            String fileName = "【翻译词条】周报告"+date+".xlsx";
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfXls)
                            .object(fileName)
                            .stream(in,in.available(),-1) // in.available() 获取文件大小
                            .build()
            );

            // 将文件名插入到数据库中
            Entry entry = new Entry();
            entry.setEntryValue(fileName);
            entry.setEntryDownloadUrl(fileName);
            entry.setEntrySize(fileSize);
            entry.setEntryType("translate");
            entry.setEntryDatetime(DateTimeUtils.currentDateTime2SQLTimestamp());
            entryMapper.insert(entry);

            log.info("翻译词条信息，已执行");
        } catch (Exception e) {
            log.error(e.toString());
        } finally {
            // 10、关闭流
            if (in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null){
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (os != null){
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }




    /**
     * 将字节转换成对应的KB、MB、GB
     * @param size
     * @return
     */
    @NotNull
    public static String  getSize(int size) {
        double result = 0;
        String unit = "字节";
        long length = size;
        if (length < 1024) {
            result = length;
        } else if (length < 1024 * 1024) {
            result = length / 1024.0;
            unit = "KB";
        } else if (length < 1024 * 1024 * 1024) {
            result = length / 1024.0 / 1024;
            unit = "MB";
        } else {
            result = length / 1024.0 / 1024 / 1024;
            unit = "GB";
        }
        BigDecimal bigDecimal=new BigDecimal(result+"",new MathContext(3));
        return bigDecimal.doubleValue()+unit;
    }
}
